package com.fer.tankr.models;

import org.andengine.engine.handler.IUpdateHandler;
import org.andengine.entity.primitive.Rectangle;
import org.andengine.entity.sprite.Sprite;
import org.andengine.extension.physics.box2d.PhysicsFactory;
import org.andengine.extension.physics.box2d.PhysicsWorld;
import org.andengine.extension.physics.box2d.util.Vector2Pool;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
import org.andengine.util.math.MathUtils;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.fer.andenginemvc.api.gameObjects.GameObject;
import com.fer.tankr.huds.IHud;
import com.fer.tankr.models.enemies.Enemy;

public class Tank extends GameObject<Rectangle> {

	private int coins;
	private int bullets;
	private int lives;
	private IHud hud;
	
	private long millisElapsed;
	
	public Sprite cannon;
	
	public Tank(PhysicsWorld world, VertexBufferObjectManager vbom, IHud hud, ITextureRegion texture, ITextureRegion textureCannon) {
		super(world, vbom, new Rectangle(0, 0, 18, 30, vbom));
		cannon = new Sprite(0, 0, textureCannon, vbom);
		cannon.setWidth(entity.getWidth());
		cannon.setHeight(entity.getHeight());
		cannon.setRotationCenter(8,20);
		cannon.attachChild(new Rectangle(cannon.getRotationCenterX(), cannon.getRotationCenterY(), 2, 2, vbom));
		
		
		attachSprite(texture, 0, 0);
		
		body.setAngularDamping(5f);
		this.hud = hud;
		
		resetTank();
		millisElapsed = 0;
		
		entity.registerUpdateHandler(new IUpdateHandler() {
			
			@Override
			public void reset() {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onUpdate(float pSecondsElapsed) {
				updateHud();
				Tank.this.cannon.setPosition(entity);
				Tank.this.cannon.setY(Tank.this.cannon.getY()-5);
			}
		});
	}
	
	
	
	private void updateHud()
	{
		hud.setBullets(bullets);
		hud.setCoins(coins);
		hud.setLives(lives);
	}
	
	public GameObject<?> fire(Vector2 direction)
	{
		long time = System.currentTimeMillis();
		if (bullets>0 && time-millisElapsed> 0.8)
		{
			float separator = Math.max(entity.getWidth(), entity.getHeight());
			float x = entity.getX() + entity.getWidth()/2 + direction.x*separator;
			float y = entity.getY() + entity.getWidth()/2 + direction.y*separator;
			float angle = MathUtils.radToDeg((float) Math.atan2(-direction.x, direction.y))+180;
			cannon.setRotation(angle);
			
			
			Bullet bullet = new Bullet(physWorld, vbom,x,y);
			bullet.setDirection(direction);
			bullets--;
			millisElapsed = System.currentTimeMillis();
			return bullet;
		}
		return null;
	}


	@Override
	public Body initBody() {
		return PhysicsFactory.createBoxBody(physWorld, entity, BodyType.DynamicBody, fixtureDef);
	}

	@Override
	public FixtureDef initFixtureDef() {
		return PhysicsFactory.createFixtureDef(1, 0f, 0.5f);
	}
	
	public void move(float xDir, float yDir)
	{
		final Body carBody = body;

		final Vector2 velocity = Vector2Pool.obtain(xDir * 5, yDir * 5);
		if (velocity.len()>=1)
		{
			carBody.setLinearVelocity(velocity);
			

			carBody.setAngularVelocity(0f);
			float rotationInRad = (float)Math.atan2(-xDir, yDir);
			carBody.setTransform(carBody.getWorldCenter(), rotationInRad);
			entity.setRotation(MathUtils.radToDeg(rotationInRad));
		}
		else
		{
			carBody.setLinearVelocity(0,0);
		}
		Vector2Pool.recycle(velocity);
	}


	public void increaseCoins(int amount)
	{
		coins +=amount;
	}
	
	public void increaseLives(int amount)
	{
		lives+=amount;
	}
	
	public void inscreaseBullets(int amount)
	{
		bullets+=amount;
	}
	
	public boolean reduceLives()
	{
		lives--;
		if (lives==0)
		{
			return true;
		}
		return false;
	}
	
	public boolean isDead()
	{
		return lives<=0;
	}

	public void resetTank() {
		coins = 0;
	}
	
	@Override
	public void onCollision(GameObject<?> go) {
		if (go instanceof Enemy)
		{
			reduceLives();
		}
	}



	public void setBullets(int ammo) {
		bullets = ammo;
	}
	
	public void setLives(int lives)
	{
		this.lives = lives;
	}
	

}
